/**
 * Copyright (c) 2011 eelpo.com
 * All rights reserved.
 */
package com.eelpo.common.security;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;

import com.eelpo.common.encoder.BASE64DecoderStream;
import com.eelpo.common.encoder.BASE64EncoderStream;
import com.eelpo.common.security.constant.Constants;
import com.eelpo.common.util.BlankUtils;
import com.eelpo.common.util.StringUtils;

/**
 * 功能描述：RC4对称算法信息加密器
 * <p>
 * 版权所有：广州市艾尔博科技有限公司
 * <p>
 * 未经本公司许可，不得以任何方式复制或使用本程序任何部分
 * 
 * @author <a href="mailto:Brian@eelpo.com">汪洪州</a>
 * 
 * @since 1.0
 */
public class RC4AlgorithmEncryptor {

	// 密钥
	private Key key;

	public RC4AlgorithmEncryptor() {

	}

	// constructor
	public RC4AlgorithmEncryptor(Key key) {
		this.key = key;
	}

	public Key getKey() {
		return key;
	}

	public void setKey(Key key) {
		this.key = key;
	}

	/**
	 * <p>
	 * 方法用途和描述：加密字符串明文
	 * </p>
	 * 
	 * @param plainText
	 *            ：要加密的字符串明文
	 * @return 加密后的字符串密文
	 */
	public String encrypt(String plainText) {

		if (BlankUtils.isBlank(plainText)) {
			return StringUtils.EMPTY;
		}

		return BASE64EncoderStream.encode(decrypt(plainText.getBytes()));

	}

	/**
	 * <p>
	 * 方法用途和描述：加密字符数组
	 * </p>
	 * 
	 * @param plainBytes
	 *            ：要加密的字符数组
	 * @return 返回字符数组密文
	 */
	public byte[] encrypt(byte[] plainBytes) {

		if (BlankUtils.isBlank(plainBytes)) {
			return new byte[] {};
		}

		try {

			Cipher cipher = getCipher(Cipher.ENCRYPT_MODE);
			return cipher.doFinal(plainBytes);

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * <p>
	 * 方法用途和描述：加密文件
	 * </p>
	 * 
	 * @param inputPath
	 *            ：要加密的文件路径
	 * @param outputPath
	 *            ：加密后的输出文件路径
	 */
	public void encrypt(String inputPath, String outputPath) {

		try {

			FileInputStream inputStream = new FileInputStream(inputPath);
			FileOutputStream outputStream = new FileOutputStream(outputPath);

			Cipher cipher = getCipher(Cipher.ENCRYPT_MODE);

			CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);
			for (int i = cipherInputStream.read(); i != -1; i = cipherInputStream.read())
				outputStream.write(i);

			outputStream.close();
			inputStream.close();
			cipherInputStream.close();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * <p>
	 * 方法用途和描述：解密字符串密文
	 * </p>
	 * 
	 * @param cipherText
	 *            ：要解密的字符串密文
	 * @return 返回解密过的字符串明文
	 */
	public String decrypt(String cipherText) {

		if (BlankUtils.isBlank(cipherText)) {
			return StringUtils.EMPTY;
		}

		return new String(decrypt(BASE64DecoderStream.decode(cipherText)));
	}

	/**
	 * <p>
	 * 方法用途和描述：解密字符数组
	 * </p>
	 * 
	 * @param cipherBytes
	 *            ：要解密的自负数组
	 * @return 返回解密后的字符数组
	 */
	public byte[] decrypt(byte[] cipherBytes) {

		if (BlankUtils.isBlank(cipherBytes)) {
			return new byte[] {};
		}

		try {

			Cipher cipher = getCipher(Cipher.DECRYPT_MODE);
			return cipher.doFinal(cipherBytes);

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * <p>
	 * 方法用途和描述：解密文件
	 * </p>
	 * 
	 * @param inputPath
	 *            ：要解密的文件路径
	 * @param outputPath
	 *            ：解密后的输出文件路径
	 */
	public void decrypt(String inputPath, String outputPath) {

		try {

			FileInputStream inputStream = new FileInputStream(inputPath);
			FileOutputStream outputStream = new FileOutputStream(outputPath);

			Cipher cipher = getCipher(Cipher.DECRYPT_MODE);

			CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher);
			for (int i = inputStream.read(); i != -1; i = inputStream.read())
				cipherOutputStream.write(i);

			inputStream.close();
			outputStream.close();
			cipherOutputStream.close();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/*
	 * <p> 方法用途和描述：获取加密解密器 </p>
	 * 
	 * @param mode：加密解密器的模式
	 * 
	 * @return 返回加密解密器对象
	 */
	private Cipher getCipher(int mode) {

		try {

			Cipher cipher = Cipher.getInstance(Constants.RC4_ALGORITHM);
			cipher.init(mode, key);

			return cipher;

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}
